#pragma once
#include "common.hpp"
#include "log.hpp"
#include "inetaddr.hpp"
#include <strings.h>
#include <sys/wait.h>
using namespace hllog;
using namespace hladdr;
using task_t = std::function<std::string(int fd, InetAddr &addr)>;
class TcpServer
{
    void Server(int sockfd, InetAddr &addr)
    {
        while (true)
        {
            char buff[256];
            int n = read(sockfd, buff, sizeof(buff) - 1);
            if (n < 0)
            {
                LOG(Level::WARNING) << "read error";
                break;
            }
            else if (n == 0)
            {
                LOG(Level::INFO) << "write exit";
                break;
            }
            buff[n] = '\0';
            std::cout << addr.ToString() << " : " << buff << std::endl;
            std::string reply = "server : ";
            reply += buff;
            write(sockfd, reply.c_str(), reply.size());
        }
    }

public:
    TcpServer(uint16_t port, task_t task) : _listenfd(-1), _port(port), _task(task)
    {
    }
    ~TcpServer() {}
    void Init()
    {
        // 1. 创建socket
        _listenfd = socket(AF_INET, SOCK_STREAM, 0);
        if (_listenfd < 0)
        {
            LOG(Level::FATAL) << "socket error";
            exit(SOCKET_ERR);
        }
        LOG(Level::INFO) << "socket success";
        // 2. bind
        InetAddr addr(_port);
        int b = bind(_listenfd, addr.GetInetAddr(), addr.GetLen());
        if (b < 0)
        {
            LOG(Level::FATAL) << "bind error";
            exit(BIND_ERR);
        }
        LOG(Level::INFO) << "bind success";
        // 3. listen
        int l = listen(_listenfd, 5);
        if (l < 0)
        {
            LOG(Level::FATAL) << "listen error";
            exit(LISTEN_ERR);
        }
        LOG(Level::INFO) << "listen success";
    }
    class ThreadData
    {
    public:
        ThreadData(int sockfd, InetAddr &addr, TcpServer *ptsvr)
            : _sockfd(sockfd), _addr(addr), _ptsvr(ptsvr)
        {
        }
        int _sockfd;
        InetAddr _addr;
        TcpServer *_ptsvr;
    };
    static void *Routinue(void *argv)
    {
        pthread_detach(pthread_self()); // 线程分离
        ThreadData *td = static_cast<ThreadData *>(argv);
        td->_ptsvr->Server(td->_sockfd, td->_addr);
        delete td;
        return nullptr;
    }
    void Start()
    {
        while (true)
        {
            // 获取请求
            struct sockaddr_in peer;
            bzero(&peer, sizeof(peer));
            socklen_t len = sizeof(peer);
            int sockfd = accept(_listenfd, (struct sockaddr *)&peer, &len);
            if (sockfd < 0)
            {
                LOG(Level::FATAL) << "accept error";
                exit(ACCEPT_ERR);
            }
            LOG(Level::INFO) << "accept success";
            // 接受信息

            // 一、单进程
            // Server(sockfd);

            // 二、多进程
            //  pid_t pid = fork();
            //  if (pid < 0)
            //  {
            //      LOG(Level::FATAL) << "fork error";
            //      exit(FORK_ERR);
            //  }
            //  else if (pid == 0)
            //  {
            //      // 子进程
            //      //  1. 设置CHLD信号处理方式为 SIG_IGN / 自定义捕捉
            //      //  2. 创建孙子进程
            //      close(_listenfd);
            //      if (fork() == 0)
            //          Server(sockfd);
            //      exit(1);
            //  }
            //  close(sockfd);
            //  waitpid(pid, nullptr, 0);

            // // // 三、多线程
            // InetAddr addr(peer);
            // ThreadData *td = new ThreadData(sockfd, addr, this);
            // pthread_t tid;
            // pthread_create(&tid, nullptr, Routinue, td);
            // LOG(Level::DEBUG) << "create thread";
            _task();
        }
    }

private:
    int _listenfd;
    uint16_t _port;
    task_t _task;
};